package report

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"git.mycaigou.com/gfyx/common/usermetadata"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/constants"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/errcode"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/msg_center"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/utils"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/msg"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/base/user"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/clue/clue"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/clue/crm"
	contract5 "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/clue/crm/contract"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/clue/crm/gfyx_crm_config"
	crmRelation2 "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/clue/crm/gfyx_crm_relation"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/clue/report"
	contract3 "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/common/form"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/remote/openapi_remote"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/repository/remote/opensearch_remote"
	businessOpportunityPb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/business_opportunity"
	cluePb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/clue"
	opptyStatusService "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/service/business_opportunity/oppty_status"
	"git.myscrm.cn/golang/common/ykerrcode"
	"git.myscrm.cn/golang/stark/v4"
	"github.com/golang/protobuf/jsonpb"
	"github.com/google/uuid"
	"strconv"
	"strings"
	"time"
)

type OpptyReportService struct {
	reportFollowRecordRepos report.GfyxReportFollowRecordReposIface
	gfyxReportRepos         report.GfyxReportReposIface
	formRepo                contract3.FormRepoIface
	clueRepo                clue.ClueRepositoryIface
	msgRepo                 msg.MsgRepositoryIface
	crmConfigRepo           gfyx_crm_config.GfyxCrmConfigRepositoryIface
	crmRelationRepo         crmRelation2.GfyxCrmRelationRepositoryIface
	companyRepo             openapi_remote.OpenApiRepoIface
	opptyStatusService      opptyStatusService.OpptyStatusServiceIface
	userBindRepos           user.GfyxUserBindReposIface
	userOrgRepo             user.UserOrgRepositoryIface
	userRepo                user.UserRepositoryIface
	openSearchRepos         opensearch_remote.OpenSearchRepositoryIface
}

func NewReportService(
	reportFollowRecordRepos report.GfyxReportFollowRecordReposIface,
	gfyxReportRepos report.GfyxReportReposIface,
	formRepo contract3.FormRepoIface,
	clueRepo clue.ClueRepositoryIface,
	msgRepo msg.MsgRepositoryIface,
	crmConfigRepo gfyx_crm_config.GfyxCrmConfigRepositoryIface,
	crmRelationRepo crmRelation2.GfyxCrmRelationRepositoryIface,
	opptyStatusService opptyStatusService.OpptyStatusServiceIface,
	companyRepo openapi_remote.OpenApiRepoIface,
	userBindRepos user.GfyxUserBindReposIface,
	userOrgRepo user.UserOrgRepositoryIface,
	userRepo user.UserRepositoryIface,
	openSearchRepos opensearch_remote.OpenSearchRepositoryIface,
) OpptyReportServiceIface {
	return &OpptyReportService{
		reportFollowRecordRepos: reportFollowRecordRepos,
		gfyxReportRepos:         gfyxReportRepos,
		formRepo:                formRepo,
		clueRepo:                clueRepo,
		msgRepo:                 msgRepo,
		crmConfigRepo:           crmConfigRepo,
		crmRelationRepo:         crmRelationRepo,
		companyRepo:             companyRepo,
		opptyStatusService:      opptyStatusService,
		userBindRepos:           userBindRepos,
		userOrgRepo:             userOrgRepo,
		userRepo:                userRepo,
		openSearchRepos:         openSearchRepos,
	}
}

func (o *OpptyReportService) TestTenantDbEnable(ctx context.Context, request *cluePb.TestTenantDbEnableRequest) (*cluePb.TestTenantDbEnableResponse, error) {
	_, err := o.gfyxReportRepos.TestTenantDbEnable(ctx, request)
	testTenantDbEnableResponse := &cluePb.TestTenantDbEnableResponse{}
	if err != nil {
		return nil, err
	}
	return testTenantDbEnableResponse, nil
}

func (o *OpptyReportService) GetReportList(ctx context.Context, request *cluePb.GetReportListRequest) (*cluePb.GetReportListResponse, error) {
	// 构建查询参数
	result := &cluePb.GetReportListResponse{}
	total, err := o.gfyxReportRepos.GetMyReportListCount(ctx, request)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取我的报备列表总数，错误信息：", err)
		return nil, err
	}
	result.Total = int32(total)
	if result.Total <= 0 {
		result.Total = 0
		return result, nil
	}

	list, err := o.gfyxReportRepos.GetMyReportList(ctx, request)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取我的报备列表失败，错误信息：", err)
		return nil, err
	}

	if list != nil {
		for _, item := range list {
			result.List = append(result.List, &cluePb.ReportInfo{
				Uid:                   item.Uid,
				ProjectTitle:          item.ProjectTitle,
				FollowStatus:          item.FollowStatus,
				Submitter:             item.Submitter,
				CompanyName:           item.CompanyName,
				ResponsiblePersonName: item.ResponsiblePersonName,
				ResponsiblePersonGuid: item.ResponsiblePersonGuid,
				AgencyName:            item.AgencyName,
				AgencyContact:         item.AgencyContact,
				ProjectCityCode:       item.ProjectCityCode,
				ProjectProvinceCode:   item.ProjectProvinceCode,
				CreatedOn:             item.CreatedOn.Format("2006-01-02 15:04:05"),
				ModifiedOn:            item.ModifiedOn.Format("2006-01-02 15:04:05"),
			})
		}
	}

	return result, nil
}

func (o *OpptyReportService) GetRegionReportList(ctx context.Context, request *cluePb.GetReportListRequest) (*cluePb.GetReportListResponse, error) {
	// 初始化变量
	result := &cluePb.GetReportListResponse{}
	result.List = make([]*cluePb.ReportInfo, 0)
	// todo 直接传用户id 而不是 guid
	userPo, err := o.userRepo.GetUserByCondition(ctx, map[string]interface{}{"uid": request.UserId})
	if err != nil {
		stark.Logger.Errorf(ctx, "获取用户信息失败，用户uid：%s, 错误信息：%+v", request.UserId, err)
		return nil, errors.New("用户不存在，id:" + request.UserId)
	}
	// 先获取我负责的区域所有的用户id，再获取报备信息
	userIds, err := o.userOrgRepo.GetMyResponseOrgUserGuids(ctx, userPo.Id)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取所属区域的用户列表失败，用户id：%d, 错误信息：%+v", userPo.Id, err)
		return nil, errors.New("获取所属区域的用户列表失败，用户id:" + request.UserId)
	}
	subUserIds, err := o.userOrgRepo.GetMyResponseSubOrgUserGuids(ctx, userPo.Id)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取所属区域的子区域用户列表失败，用户id：%d, 错误信息：%+v", userPo.Id, err)
		return nil, errors.New("获取所属区域的子区域用户列表失败，用户id:" + request.UserId)
	}
	userIds = append(userIds, subUserIds...)
	pageInfo := &utils.PageInfo{
		Page:     int(request.Page),
		PageSize: int(request.PageSize),
	}
	// 拼接条件
	condition := map[string]interface{}{"user_ids": userIds, "is_deleted": constants.IsDeletedFalse}
	if request.GetResponsiblePersonGuid() != "" {
		condition["responsible_person_guid"] = request.GetResponsiblePersonGuid()
	}
	if request.GetProjectProvinceCode() != "" && request.GetProjectProvinceCode() != "0" {
		condition["project_province_code"] = request.GetProjectProvinceCode()
	}
	if request.GetProjectCityCode() != "" {
		condition["project_city_code"] = request.GetProjectCityCode()
	}
	if request.GetCompanyProvinceCode() != "" {
		condition["company_province_code"] = request.GetCompanyProvinceCode()
	}
	if request.GetCompanyCityCode() != "" {
		condition["company_city_code"] = request.GetCompanyCityCode()
	}
	if request.GetSubmitStartTime() != "" && request.GetSubmitEndTime() != "" {
		condition["created_on_start"] = request.GetSubmitStartTime()
		condition["created_on_end"] = request.GetSubmitEndTime()
	}
	if request.GetFollowStatus() > 0 {
		condition["follow_status"] = request.GetFollowStatus()
	}
	if request.GetKeyword() != "" {
		condition["keyword"] = request.GetKeyword()
	}
	total, list, err := o.gfyxReportRepos.GetReportList(ctx, condition, pageInfo)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取区域报备列表失败，错误信息：%+v", err)
		return nil, err
	}
	result.Total = int32(total)
	if len(list) > 0 {
		for _, item := range list {
			result.List = append(result.List, &cluePb.ReportInfo{
				Uid:                   item.Uid,
				ProjectTitle:          item.ProjectTitle,
				FollowStatus:          item.FollowStatus,
				Submitter:             item.Submitter,
				CompanyName:           item.CompanyName,
				ResponsiblePersonName: item.ResponsiblePersonName,
				ResponsiblePersonGuid: item.ResponsiblePersonGuid,
				AgencyName:            item.AgencyName,
				AgencyContact:         item.AgencyContact,
				CreatedOn:             item.CreatedOn.Format("2006-01-02 15:04:05"),
				ModifiedOn:            item.ModifiedOn.Format("2006-01-02 15:04:05"),
			})
		}
	}
	return result, nil
}

func (o *OpptyReportService) SaveFollowRecord(ctx context.Context, request *cluePb.SaveFollowRecordRequest) (resp *cluePb.SaveFollowRecordResponse, err error) {
	/*
		todo:
			校验提交跟进记录人是否有权限（负责人团队、区域负责人）
	*/

	metaUserInfo := usermetadata.GetMetaUserInfo(ctx)
	gfyxReport, err := o.gfyxReportRepos.GetReport(ctx, request.GetData().GetReportId())
	if err != nil {
		return nil, err
	}
	if gfyxReport.Uid == "" {
		return nil, errors.New("没有找到报备记录")
	}

	followUserName := metaUserInfo.UserName
	followUserId := metaUserInfo.TenantUserUid
	followGlobalUserId := metaUserInfo.CommonUserDataUid

	data := report.GfyxReportFollowRecord{
		ReportId:           request.GetData().GetReportId(),
		FollowContent:      request.GetData().GetFollowContent(),
		FollowType:         request.GetData().GetFollowType(),
		FollowStatus:       request.GetData().GetFollowStatus(),
		FollowUserId:       followUserId,
		FollowGlobalUserId: followGlobalUserId,
		FollowUserName:     followUserName,
		Province:           request.GetData().GetProvince(),
		ProvinceCode:       request.GetData().GetProvinceCode(),
		City:               request.GetData().GetCity(),
		CityCode:           request.GetData().GetCityCode(),
		Address:            request.GetData().GetAddress(),
		Images:             strings.Join(request.GetData().GetImages(), ","),
		CreatedOn:          time.Now(),
		CreatedBy:          followGlobalUserId,
		ModifiedOn:         time.Now(),
		ModifiedBy:         followGlobalUserId,
	}
	if err := o.reportFollowRecordRepos.SaveReportFollowRecrod(ctx, &data); err != nil {
		return nil, err
	}

	gfyxReport.FollowStatus = request.GetData().GetFollowStatus()
	gfyxReport.ModifiedOn = time.Now()
	if _, err := o.gfyxReportRepos.SaveReport(ctx, gfyxReport); err != nil {
		return nil, err
	}

	// 获取负责人的openid
	var openid string
	userBindPo, err := o.userBindRepos.GetUserBind(ctx, gfyxReport.ResponsiblePersonGuid)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取微信绑定信息失败:%s", err.Error())
	}
	openid = userBindPo.OpenId
	// 发送通知——微信公众号
	if openid != "" {
		msgClient := msg_center.NewClient(nil)
		openids := []string{openid}
		content := map[string]interface{}{
			"project_title": gfyxReport.ProjectTitle,
			"time":          utils.TimeToString(time.Now()),
			"follower":      data.FollowUserName,
			"report_id":     gfyxReport.Uid,
		}
		contentStr, _ := json.Marshal(content)
		msgStd := &msg_center.MsgBody{
			PushOrderCode: stark.Configer.(stark.ApolloConfigerIface).GetStringValue("PushOrderCode.ShareReportFollow", ""),
			Wx: &msg_center.MsgContent{
				ReceiverIds: openids,
				Content:     string(contentStr),
				TryTimes:    0,
				ConfirmUrl:  "",
				CallbackUrl: "",
			},
		}
		if err := msgClient.Push(ctx, msgStd); err != nil {
			stark.Logger.Errorf(ctx, "【提交跟进】消息推送[微信公众号]失败:%s", err.Error())
		}
	}

	// 通过userGuid获取userId
	userInfo, _ := o.userRepo.GetUserByCondition(ctx, map[string]interface{}{"uid": gfyxReport.ResponsiblePersonGuid})
	if userInfo == nil || userInfo.Id == 0 {
		stark.Logger.Errorf(ctx, "【提交跟进】获取用户信息失败:userGuid=%s", gfyxReport.ResponsiblePersonGuid)
	} else {
		// 发送通知——站内信
		domain := stark.Configer.(stark.ApolloConfigerIface).GetStringValue("gfyx_front_domain", "https://toker.mycaigou.com")

		msgInbox := &msg.GfyxMessageInboxPo{
			Id:           0,
			MessageType:  "线索报备",
			Title:        fmt.Sprintf("您参与【%s】报备有新的跟进记录，请及时查看", gfyxReport.ProjectTitle),
			Content:      fmt.Sprintf("您参与【%s】报备有新的跟进记录，请及时查看", gfyxReport.ProjectTitle),
			SenderId:     0,
			ReceiverId:   userInfo.Id,
			IsReaded:     2,
			ReceivedTime: time.Now(),
			Link:         fmt.Sprintf("%s/crm/report/detail?id=%s", domain, gfyxReport.Uid),
			CreatedBy:    "",
			CreatedOn:    time.Now(),
			ModifiedBy:   "",
			ModifiedOn:   time.Now(),
			IsDeleted:    0,
		}
		if err := o.msgRepo.PushSiteMsg(ctx, msgInbox); err != nil {
			stark.Logger.Errorf(ctx, "【提交跟进】消息推送[站内信]失败:%s", err.Error())
		}
	}

	resp = &cluePb.SaveFollowRecordResponse{
		IsSuccess:        true,
		ReportSourceType: gfyxReport.ReportSourceType,
		ReportSourceId:   gfyxReport.ReportSourceId,
	}
	return resp, nil
}

func (o *OpptyReportService) GetFollowRecordList(ctx context.Context, request *cluePb.GetFollowRecordListRequest) (*cluePb.GetFollowRecordListResponse, error) {
	resp := cluePb.GetFollowRecordListResponse{List: make([]*cluePb.FollowRecord, 0)}
	list, total, err := o.reportFollowRecordRepos.GetReportFollowRecrod(ctx, request.GetReportId(), request.GetPage(), request.GetPageSize())
	if err != nil {
		return nil, err
	}
	if list != nil {
		resp.Total = total
		for _, item := range list {
			images := make([]string, 0)
			if item.Images != "" {
				images = strings.Split(item.Images, ",")
			}
			resp.List = append(resp.List, &cluePb.FollowRecord{
				ReportId:         item.ReportId,
				FollowType:       item.FollowType,
				FollowStatus:     item.FollowStatus,
				FollowContent:    item.FollowContent,
				Province:         item.Province,
				ProvinceCode:     item.ProvinceCode,
				City:             item.City,
				CityCode:         item.CityCode,
				Address:          item.Address,
				Images:           images,
				FollowUserId:     item.FollowUserId,
				FollowUserName:   item.FollowUserName,
				FollowUserAvatar: item.FollowUserAvatar,
				CreatedOn:        item.CreatedOn.Format("2006-01-02 15:04:05"),
				CreatedBy:        item.CreatedBy,
				ModifiedOn:       item.ModifiedOn.Format("2006-01-02 15:04:05"),
				ModifiedBy:       item.ModifiedBy,
				Uid:              item.Uid,
			})
		}

	}
	return &resp, nil
}

func (o *OpptyReportService) CheckSaveReportParams(ctx context.Context, request *cluePb.SaveReportRequest) error {
	marshaler := jsonpb.Marshaler{}
	jsonStr, err := marshaler.MarshalToString(request)
	var params map[string]interface{}

	// 将 JSON 字符串解析到 map 变量中
	err = json.Unmarshal([]byte(jsonStr), &params)
	if err != nil {
		stark.Logger.Errorf(ctx, "保存报备信息转换json失败，err:%v", err)
		return err
	}
	condition := map[string]interface{}{
		"is_deleted":       0,
		"form_template_id": request.TemplateId,
		"required":         1,
	}
	filedList, err := o.formRepo.GetFormFieldList(ctx, condition)
	if err != nil {
		return err
	}
	var errMsg []string
	if filedList != nil {
		for _, item := range filedList {
			key := item.FieldName
			//todo 注意：如果有int型参数，需要考虑0值
			fieldName := utils.ToCamelCase(key)
			if _, ok := params[fieldName]; !ok {
				var itemMap map[string]interface{}
				err := json.Unmarshal([]byte(item.FieldComponentProps), &itemMap)
				if err != nil {
					print(err)
					errMsg = append(errMsg, key)
				} else if _, ok = itemMap["label"]; ok {
					errMsg = append(errMsg, itemMap["label"].(string))
				} else {
					errMsg = append(errMsg, key)
				}
			}
		}
	}
	if len(errMsg) > 0 {
		err = ykerrcode.TogRPCError(errcode.COMMON_PARAMS_ERROR, strings.Join(errMsg, ",")+"不能为空")
		return err
	}
	return nil
}

func (o *OpptyReportService) SaveReport(ctx context.Context, request *cluePb.SaveReportRequest) (bool, string, error) {
	//报备已存在校验规则：项目名称、企业名称、项目所在省份、城市
	condition := map[string]interface{}{}
	condition["project_title"] = request.ProjectTitle
	condition["company_name"] = request.CompanyName
	condition["project_province_code"] = request.ProjectProvinceCode
	condition["project_city_code"] = request.ProjectCityCode
	reportInfo, err := o.gfyxReportRepos.GetReportByCondition(ctx, condition)
	if err != nil {
		return false, "", err
	}
	if reportInfo != nil && reportInfo.Uid != "" {
		return false, "", ykerrcode.TogRPCError(errcode.ReportIsExistError, "报备已存在")
	}

	if request.CompanyProvinceCode == "" || request.CompanyCityCode == "" {
		//请求供应商大数据接口获取公司所在省市信息
		keyword := ""
		//优先通过企业信用码获取，企业信用码为空通过公司名查。openapi接口支持两个参数查询的方式
		if request.CompanyOrganizingCode != "" {
			keyword = request.CompanyOrganizingCode
		} else if request.CompanyName != "" {
			keyword = request.CompanyName
		}
		if keyword != "" {
			//请求替换省市code
			companyDetail, err := o.companyRepo.GetCompanyDetail(ctx, keyword)
			if err != nil {
				stark.Logger.Errorf(ctx, "获取企业信息失败，请求参数：%v,错误信息:%v", request, err)
			}
			if companyDetail.ProvinceCode != "" {
				request.CompanyProvinceCode = companyDetail.ProvinceCode
			}
			if companyDetail.CityCode != "" {
				request.CompanyCityCode = companyDetail.CityCode
			}
		}
	}

	curUser := usermetadata.GetMetaUserInfo(ctx)
	reportPo := &report.GfyxReport{
		Uid:                     uuid.New().String(),
		ReportSourceType:        request.ReportSourceType,
		ReportSourceId:          request.ReportSourceId,
		ClueSource:              request.ClueSource,
		ClueSourceId:            request.ClueSourceId,
		CompanyName:             request.CompanyName,
		CompanyOrganizingCode:   request.CompanyOrganizingCode,
		CompanyType:             request.CompanyType,
		CompanyCityCode:         request.CompanyCityCode,
		CompanyCity:             request.CompanyCity,
		CompanyProvinceCode:     request.CompanyProvinceCode,
		CompanyProvince:         request.CompanyProvince,
		DefaultContact:          request.DefaultContact,
		DefaultContactTel:       request.DefaultContactTel,
		ContactPosition:         request.ContactPosition,
		ProjectTitle:            request.ProjectTitle,
		ProjectProvinceCode:     request.ProjectProvinceCode,
		ProjectProvince:         request.ProjectProvince,
		ProjectCityCode:         request.ProjectCityCode,
		ProjectCity:             request.ProjectCity,
		ProjectAddress:          request.ProjectAddress,
		ProjectImage:            request.ProjectImage,
		ProjectType:             request.ProjectType,
		SubmitterCompany:        request.SubmitterCompany,
		Submitter:               request.Submitter,
		SubmitterTel:            request.SubmitterTel,
		AgencyName:              request.AgencyName,
		AgencyContact:           request.AgencyContact,
		AgencyContactTel:        request.AgencyContactTel,
		ResponsiblePersonGuid:   request.ResponsiblePersonGuid,
		ResponsiblePersonName:   request.ResponsiblePersonName,
		ResponsiblePersonMobile: request.ResponsiblePersonMobile,
		FollowStatus:            1, //保存报备默认是跟进中的状态 @2023-06-12
		CreatedOn:               time.Now(),
		CreatedBy:               curUser.CommonUserDataUid,
		ModifiedOn:              time.Now(),
		ModifiedBy:              curUser.CommonUserDataUid,
	}

	id, err := o.gfyxReportRepos.SaveReport(ctx, reportPo)
	if err != nil {
		return false, "", err
	}

	if id > 0 {
		err = o.sendReportToThirdCrm(ctx, reportPo)
		if err != nil {
			stark.Logger.Errorf(ctx, "sendReportToThirdCrm 提交线索到第三方crm系统失败:%s", err.Error())
		}
		stark.Logger.Infof(ctx, "sendReportToThirdCrm reportPo uid:%s,提交线索到第三方crm系统成功", reportPo.Uid)
	}
	//更新数据状态
	updateOpptyStatus := &businessOpportunityPb.UpdateOpptyStatusRequest{
		DataSource:   request.ClueSource,
		DataSourceId: request.ClueSourceId,
		Status:       constants.OpptyStatusReport,
	}
	if updateOpptyStatus.DataSource == "CLUE" { //如果是线索，则获取线索来源
		clueId, _ := strconv.ParseInt(updateOpptyStatus.DataSourceId, 10, 64)
		clueInfo, _ := o.clueRepo.ClueDetail(ctx, clueId)
		if clueInfo != nil && clueInfo.SourceId != "" {
			switch clueInfo.Source {
			case constants.ClueSourceBid:
				updateOpptyStatus.DataSource = constants.OpptySourcePurchase
			case constants.ClueSourceWinbid:
				updateOpptyStatus.DataSource = constants.OpptySourceWinBid
			case constants.ClueSourceLand:
				updateOpptyStatus.DataSource = constants.OpptySourceLand
			case constants.ClueSourceBuilding:
				updateOpptyStatus.DataSource = constants.OpptySourceBuilding
			case constants.ClueSourceSale:
				updateOpptyStatus.DataSource = constants.OpptySourceSale
			case constants.ClueSourceCustomer:
				updateOpptyStatus.DataSource = constants.OpptySourceCustomer
			case constants.ClueSourceProject:
				updateOpptyStatus.DataSource = constants.OpptySourceProjectCycle
			}
			updateOpptyStatus.DataSourceId = clueInfo.SourceId
		}
	}
	if request.ReportSourceType == "DIRECT" {
		updateOpptyStatus.FromDevice = constants.FromDevicePc
	} else {
		updateOpptyStatus.FromDevice = constants.FromDeviceClueMini
	}
	if updateOpptyStatus.DataSource != "CLUE" {
		_, _ = o.opptyStatusService.UpdateOpptyStatus(ctx, updateOpptyStatus)
	}

	var openid string
	userBindPo, err := o.userBindRepos.GetUserBind(ctx, reportPo.ResponsiblePersonGuid)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取微信绑定信息失败:%s", err.Error())
	}
	openid = userBindPo.OpenId

	// 报备来源不是直接报备，则发送通知
	if reportPo.ReportSourceType != "DIRECT" {
		// 发送通知——微信公众号
		if openid != "" {
			msgClient := msg_center.NewClient(nil)
			openids := []string{openid}
			content := map[string]interface{}{
				"project_title": reportPo.ProjectTitle,
				"time":          utils.TimeToString(reportPo.CreatedOn),
				"reporter":      reportPo.Submitter,
				"report_id":     reportPo.Uid,
			}
			contentStr, _ := json.Marshal(content)
			msgStd := &msg_center.MsgBody{
				PushOrderCode: stark.Configer.(stark.ApolloConfigerIface).GetStringValue("PushOrderCode.ShareReport", ""),
				Wx: &msg_center.MsgContent{
					ReceiverIds: openids,
					Content:     string(contentStr),
					TryTimes:    0,
					ConfirmUrl:  "",
					CallbackUrl: "",
				},
			}
			if err := msgClient.Push(ctx, msgStd); err != nil {
				stark.Logger.Errorf(ctx, "【提交报备】消息推送失败:%s", err.Error())
			}
		}

		// 通过userGuid获取userId
		userInfo, _ := o.userRepo.GetUserByCondition(ctx, map[string]interface{}{"uid": reportPo.ResponsiblePersonGuid})
		if userInfo == nil || userInfo.Id == 0 {
			stark.Logger.Errorf(ctx, "【提交报备】获取用户信息失败:userGuid=%s", reportPo.ResponsiblePersonGuid)
		} else {
			// 发送通知——站内信
			domain := stark.Configer.(stark.ApolloConfigerIface).GetStringValue("gfyx_front_domain", "https://toker.mycaigou.com")
			msgInbox := &msg.GfyxMessageInboxPo{
				Id:           0,
				MessageType:  "线索报备",
				Title:        fmt.Sprintf("您在微信分享的市场信息【%s】，已被【%s】报备，感谢您的分享，团结协作，共创辉煌", reportPo.ProjectTitle, reportPo.Submitter),
				Content:      fmt.Sprintf("您在微信分享的市场信息【%s】，已被【%s】报备，感谢您的分享，团结协作，共创辉煌", reportPo.ProjectTitle, reportPo.Submitter),
				SenderId:     0,
				ReceiverId:   userInfo.Id,
				IsReaded:     2,
				ReceivedTime: time.Now(),
				Link:         fmt.Sprintf("%s/crm/report/detail?id=%s", domain, reportPo.Uid),
				CreatedBy:    "",
				CreatedOn:    time.Now(),
				ModifiedBy:   "",
				ModifiedOn:   time.Now(),
				IsDeleted:    0,
			}
			if err := o.msgRepo.PushSiteMsg(ctx, msgInbox); err != nil {
				stark.Logger.Errorf(ctx, "【提交报备】消息推送[站内信]失败:%s", err.Error())
			}
		}
	}

	return id > 0, reportPo.Uid, nil
}

func (o *OpptyReportService) sendReportToThirdCrm(ctx context.Context, report *report.GfyxReport) error {
	_, list, err := o.crmConfigRepo.Query(ctx, map[string]interface{}{"is_deleted": constants.IsDeletedFalse}, nil)
	if err != nil {
		return err
	}
	if len(list) == 0 {
		return nil
	}
	hasCrmFlag, crmServer := crm.AllCrm.GetCRMBySystemName(list[0].System)
	if hasCrmFlag {
		clueId, err := crmServer.CreateClue(ctx, &contract5.CrmData{
			BusinessUid:             report.Uid,
			BusinessType:            constants.CrmBusinessTypeReport,
			CompanyName:             report.CompanyName,
			UserName:                report.DefaultContact,
			UserMobile:              report.DefaultContactTel,
			UserPosition:            report.ContactPosition,
			Province:                report.ProjectProvince,
			City:                    report.ProjectCity,
			ResponsiblePersonMobile: report.ResponsiblePersonMobile,
		}, nil)
		if err != nil {
			return err
		}

		err = o.crmRelationRepo.Save(ctx, &crmRelation2.GfyxCrmRelationPo{
			Uid:          uuid.New().String(),
			BusinessUid:  report.Uid,
			BusinessType: constants.CrmBusinessTypeReport,
			CrmUid:       clueId,
			CreatedOn:    time.Now(),
			CreatedBy:    "",
			ModifiedOn:   time.Now(),
			ModifiedBy:   "",
			IsDeleted:    constants.IsDeletedFalse,
		})
		if err != nil {
			return err
		}
	}

	return nil
}

func (o *OpptyReportService) GetReport(ctx context.Context, reportId string) (*cluePb.GetReportResponse, error) {
	reportPo, err := o.gfyxReportRepos.GetReport(ctx, reportId)
	if err != nil {
		return nil, err
	} else if reportPo.Uid == "" {
		return nil, errors.New("记录不存在")
	}

	resp := cluePb.GetReportResponse{
		Uid:                   reportPo.Uid,
		ReportSourceType:      reportPo.ReportSourceType,
		ReportSourceId:        reportPo.ReportSourceId,
		CompanyName:           reportPo.CompanyName,
		CompanyOrganizingCode: reportPo.CompanyOrganizingCode,
		CompanyType:           reportPo.CompanyType,
		CompanyCityCode:       reportPo.CompanyCityCode,
		CompanyCity:           reportPo.CompanyCity,
		CompanyProvinceCode:   reportPo.CompanyProvinceCode,
		CompanyProvince:       reportPo.CompanyProvince,
		DefaultContact:        reportPo.DefaultContact,
		DefaultContactTel:     reportPo.DefaultContactTel,
		ContactPosition:       reportPo.ContactPosition,
		ProjectTitle:          reportPo.ProjectTitle,
		ProjectProvinceCode:   reportPo.ProjectProvinceCode,
		ProjectProvince:       reportPo.ProjectProvince,
		ProjectCityCode:       reportPo.ProjectCityCode,
		ProjectCity:           reportPo.ProjectCity,
		ProjectAddress:        reportPo.ProjectAddress,
		ProjectImage:          reportPo.ProjectImage,
		ProjectType:           reportPo.ProjectType,
		SubmitterCompany:      reportPo.SubmitterCompany,
		Submitter:             reportPo.Submitter,
		SubmitterTel:          reportPo.SubmitterTel,
		AgencyName:            reportPo.AgencyName,
		AgencyContact:         reportPo.AgencyContact,
		AgencyContactTel:      reportPo.AgencyContactTel,
		ResponsiblePersonGuid: reportPo.ResponsiblePersonGuid,
		ResponsiblePersonName: reportPo.ResponsiblePersonName,
		CreatedOn:             reportPo.CreatedOn.Format("2006-01-02 15:04:05"),
		CreatedBy:             reportPo.CreatedBy,
		ModifiedOn:            reportPo.ModifiedOn.Format("2006-01-02 15:04:05"),
		ModifiedBy:            reportPo.ModifiedBy,
		FollowStatus:          reportPo.FollowStatus,
	}
	return &resp, nil
}

func (o *OpptyReportService) GetReportSourceInfo(ctx context.Context, sourceType, sourceId string) (*cluePb.GetReportSourceInfoResponse, error) {
	curUser := usermetadata.GetMetaUserInfo(ctx)
	resp := &cluePb.GetReportSourceInfoResponse{
		Submitter:        curUser.UserName,
		SubmitterCompany: curUser.TenantName,
		SubmitterTel:     curUser.MobilePhone,
	}
	if sourceType == "" {
		return resp, nil
	}
	if sourceType != "CLUE" {
		err := ykerrcode.TogRPCError(errcode.COMMON_PARAMS_ERROR, "暂仅支持线索类型的数据")
		return resp, err
	}
	clueId, err := strconv.ParseInt(sourceId, 10, 64)
	if err != nil {
		return nil, errors.New("线索id参数错误")
	}
	clueInfo, err := o.clueRepo.ClueDetail(ctx, clueId)
	if err != nil {
		return resp, err
	}
	if clueInfo == nil {
		return resp, ykerrcode.TogRPCError(errcode.COMMON_DATA_NOT_EXIST, "线索不存在")
	}

	resp.CompanyName = clueInfo.CompanyName
	resp.CompanyOrganizingCode = clueInfo.OrganizingCode
	resp.DefaultContact = clueInfo.ContactName
	resp.DefaultContactTel = clueInfo.ContactMobile
	resp.ContactPosition = clueInfo.ContactPosition
	resp.SubmitterCompany = curUser.TenantName //当前租户中文名
	resp.Submitter = curUser.UserName
	resp.SubmitterTel = curUser.MobilePhone
	resp.ResponsiblePersonName = curUser.UserName
	resp.ResponsiblePersonGuid = curUser.TenantUserUid

	if clueInfo.OrganizingCode != "" {
		//公司的社会信用代码不为空，则从客户主档案中获取公司信息
		details, _ := o.openSearchRepos.GetCustomerDetail(ctx, &opensearch_remote.GetCustomerDetailRequest{OrganizingCodes: clueInfo.OrganizingCode})
		if len(details) > 0 {
			resp.CompanyType = details[0].CompanyType
			resp.CompanyCityCode = details[0].CityCode
			resp.CompanyCity = details[0].City
			resp.CompanyProvinceCode = details[0].ProvinceCode
			resp.CompanyProvince = details[0].Province
		}
	}
	return resp, nil
}

func (o *OpptyReportService) GetTeamLeader(ctx context.Context, reportUid string) (*cluePb.GetTeamLeaderResponse, error) {
	resp := &cluePb.GetTeamLeaderResponse{}

	reportPo, err := o.gfyxReportRepos.GetReport(ctx, reportUid)
	if err != nil {
		return nil, err
	}
	if reportPo == nil || reportPo.Uid == "" {
		return resp, nil
	}
	if reportPo.ResponsiblePersonName != "" {
		leader := &cluePb.Leader{}
		leader.UserName = reportPo.ResponsiblePersonName
		leader.Role = 1
		resp.List = append(resp.List, leader)
	}
	if reportPo.Submitter != "" && reportPo.ResponsiblePersonName != reportPo.Submitter {
		leader := &cluePb.Leader{}
		leader.UserName = reportPo.Submitter
		leader.Role = 0
		resp.List = append(resp.List, leader)
	}

	return resp, nil
}

func (o *OpptyReportService) MyReportStat(ctx context.Context, _ *cluePb.MyReportStatRequest) (*cluePb.MyReportStatResponse, error) {
	// 构建查询参数
	result := &cluePb.MyReportStatResponse{}
	metaUserInfo := usermetadata.GetMetaUserInfo(ctx)
	requestNew := &cluePb.GetReportListRequest{
		ResponsiblePersonGuid: metaUserInfo.TenantUserUid,
		FollowStatus:          1,
	}
	followCnt, err := o.gfyxReportRepos.GetMyReportListCount(ctx, requestNew)
	result.FollowCnt = int32(followCnt)

	requestNew.FollowStatus = 2
	signCnt, err := o.gfyxReportRepos.GetMyReportListCount(ctx, requestNew)
	result.SignCnt = int32(signCnt)

	requestNew.FollowStatus = 3
	noSignCnt, err := o.gfyxReportRepos.GetMyReportListCount(ctx, requestNew)
	result.NoSignCnt = int32(noSignCnt)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取我的报备总数，错误信息：", err)
		return nil, err
	}
	return result, nil
}

// GetUserList 获取负责人列表
func (o *OpptyReportService) GetUserList(ctx context.Context, _ *cluePb.GetUserListRequest) (*cluePb.GetUserListResponse, error) {
	list, err := o.gfyxReportRepos.GetUserList(ctx)
	if err != nil {
		return nil, err
	}

	result := &cluePb.GetUserListResponse{}
	if list != nil {
		for _, item := range list {
			result.List = append(result.List, &cluePb.UserOption{
				UserGuid: item.UserGUID,
				UserName: item.UserName,
			})
		}
	}

	return result, nil
}

// SendShareReceiveMsg 发送分享领取通知
func (o *OpptyReportService) SendShareReceiveMsg(ctx context.Context, req *cluePb.SendShareReceiveMsgRequest) error {
	// 获取负责人的openid
	var openid string
	userBindPo, err := o.userBindRepos.GetUserBind(ctx, req.GetShareUserTenantId())
	if err != nil {
		stark.Logger.Errorf(ctx, "获取微信绑定信息失败:%s", err.Error())
	}
	openid = userBindPo.OpenId

	// 发送通知——微信公众号
	if openid != "" {
		muteMobile := ""
		if req.GetReceiveMobile() != "" {
			muteMobile = req.GetReceiveMobile()[0:3] + "****" + req.GetReceiveMobile()[7:11]
		}

		msgClient := msg_center.NewClient(nil)
		openids := []string{openid}
		content := map[string]interface{}{
			"project_title": req.GetProjectTitle(),
			"time":          utils.TimeToString(time.Now()),
			"receiver":      muteMobile,
		}
		contentStr, _ := json.Marshal(content)
		msgStd := &msg_center.MsgBody{
			PushOrderCode: stark.Configer.(stark.ApolloConfigerIface).GetStringValue("PushOrderCode.ShareReceive", ""),
			Wx: &msg_center.MsgContent{
				ReceiverIds: openids,
				Content:     string(contentStr),
				TryTimes:    0,
				ConfirmUrl:  "",
				CallbackUrl: "",
			},
		}
		if err := msgClient.Push(ctx, msgStd); err != nil {
			stark.Logger.Errorf(ctx, "【分享领取】消息推送失败:%s", err.Error())
		}
	}

	// 通过userGuid获取userId
	userInfo, _ := o.userRepo.GetUserByCondition(ctx, map[string]interface{}{"uid": req.GetShareUserTenantId()})
	if userInfo == nil || userInfo.Id == 0 {
		stark.Logger.Errorf(ctx, "【分享领取】获取用户信息失败:userGuid=%s", req.GetShareUserTenantId())
	} else {
		// 发送通知——站内信
		msgInbox := &msg.GfyxMessageInboxPo{
			Id:           0,
			MessageType:  "线索报备",
			Title:        fmt.Sprintf("您在微信分享的市场信息【%s】已被领取，感谢您的分享，团结协作，共创辉煌", req.GetProjectTitle()),
			Content:      fmt.Sprintf("您在微信分享的市场信息【%s】已被领取，感谢您的分享，团结协作，共创辉煌", req.GetProjectTitle()),
			SenderId:     0,
			ReceiverId:   userInfo.Id,
			IsReaded:     2,
			ReceivedTime: time.Now(),
			Link:         "",
			CreatedBy:    "",
			CreatedOn:    time.Now(),
			ModifiedBy:   "",
			ModifiedOn:   time.Now(),
			IsDeleted:    0,
		}
		if err := o.msgRepo.PushSiteMsg(ctx, msgInbox); err != nil {
			stark.Logger.Errorf(ctx, "【分享领取】消息推送[站内信]失败:%s", err.Error())
		}
	}
	return nil
}
